# -*- coding: utf-8 -*-
"""
-------------------------------------------------
  Description : 重试模块,作为装饰器调用
  Author :    Administrator
  date：     2021/10/10
-------------------------------------------------
  Change Activity:
          2021/10/10:
-------------------------------------------------
"""
import sys
import time
import traceback
from Config.config import logger


class MyRetry:
    def __init__(self,
                 times=1,
                 return_obj=None,
                 return_msg=None,
                 msg_return_params=False,
                 return_err_cause=True,
                 show_process_err=True,
                 sleep_time=0
                 ):
        """
        重试模块
        :param times: 重试次数
        :param return_obj: 重试失败会返回的对象，如果参数为None则不返回直接raise，否则返回除None外指定对象
        :param return_msg: 自定义重试失败后打印的消息
        :param msg_return_params: 是否要打印传入的参数
        :param return_err_cause: 是否打印报错原因
        :param show_process_err: 是否打印重试过程中的提示
        :param sleep_time: 暂停时间
        """
        self.times = times
        self.return_obj = return_obj
        self.return_msg = return_msg
        self.msg_return_params = msg_return_params
        self.return_err_cause = return_err_cause
        self.show_process_err = show_process_err
        self.sleep_time = sleep_time

    def __call__(self, fun):
        retry_times = self.times
        return_obj = self.return_obj
        return_msg = self.return_msg
        msg_return_params = self.msg_return_params
        return_err_cause = self.return_err_cause
        show_process_err = self.show_process_err
        sleep_time = self.sleep_time

        def retry_handle(*args, **kwargs):
            msg = f'函数: {fun} 异常\t'
            for times in range(retry_times):
                try:
                    fun_res = fun(*args, **kwargs)
                except:
                    exc_type, exc_value, exc_traceback_obj = sys.exc_info()
                    if times == retry_times - 1:
                        if return_msg is not None:
                            msg += f'消息: {return_msg}\t'
                        if return_obj is not None:
                            return return_obj
                        else:
                            msg += f'重试达到最大次数({retry_times}次\t'
                            raise
                    else:
                        if show_process_err:
                            logger.warning(f'函数: {fun.__name__} 发生异常，第{times + 1}次重试，错误原因为：{exc_value}')
                        if sleep_time:
                            time.sleep(sleep_time)
                else:
                    return fun_res
                finally:
                    try:
                        if times == retry_times - 1 and msg:
                            if msg_return_params:
                                msg += f' 参数: {args} {kwargs} '
                            if return_err_cause:
                                msg += f'原因: {str(exc_type)}: {exc_value}\ttraceback:'
                            logger.error(msg)
                            if return_err_cause:
                                traceback.print_tb(exc_traceback_obj)
                    except:
                        pass

        return retry_handle
